-
Notifications
You must be signed in to change notification settings - Fork 13.6k
New Attribute Syntax (#2569) #12538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Attribute Syntax (#2569) #12538
Conversation
Oops, forgot to remove debug print statements. |
I feel good about this solution, and commend you @thehydroimpulse for taking the initiative to push it through. @pnkfelix Can you deal without the semis? |
@pcwalton You may have an opinion too. |
@brson Added two warning statements when using the old syntax. (One for the missing |
I think the warnings should be commented out until a snapshot and the main codebase has been migrated to the new syntax, or every build will be really noisy. |
@huonw The builds were definitely way too noisy, so I commented the warnings. |
@brson if the brackets stay, i can live without the semis. (it's not worth further belaboring at that point.) If there is any chance of the square brackets going away, then I will want the semis back. But right now we continue to have a clear end-delimiter, So it's okay. |
This needs a test that a |
@brson Added the shebang test. Not sure if it's correct or not, but everything passes. |
inner_attr_bang = true; | ||
if !permit_inner { | ||
self.fatal("An inner attribute was not permitted in this context."); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a test for this case (inner attribute when you're not expecting it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, yes.
Is there a prime case for when it's not expecting one? For example, not at the top of some file/module.
fn main() {}
#![lang(foo)]
fn foo() {}
Something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a good test to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, error messages should start with lower case (i.e. "an inner ..."
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huonw Good to know, thanks.
I think @brson was thinking of a test that looks like: #![some_outer_attribute]
// ignore-license
fn main() {} Also, I don't think this should change the pretty printer right now (because we're just accepting the |
@alexcrichton Ahh, ok. I'll fix that. |
I think this is the ideal test case:
Makeing the attribute something real will prevent a false-negative that just parses the attribute as a shebang and throws it away. |
Preferably the other tests would do the same: mod foo {}
mod foo {
#![cfg(this_will_never_occur)]
}
fn main() {} then if the |
@brson @alexcrichton Added a new commit addressing all of the comments. I'll squash my commits once everything is good. |
If we're going to make further changes to the attribute syntax by removing brackets, I think it would make more sense to do it all at once. I also disagree with pnkfelix, in that I don't think that bracket-less attributes need semicolons to delimit them. They're perfectly readable without the trailing delimeter, and using semicolons there just leads people into thinking that they're statements. |
2014年2月27日 下午10:49于 "Ben Striegel" notifications@github.com写道:
|
@bstrie I guess we will just have to agree to disagree on this point. I've already posted my reasoning behind why using semicolons as a terminator is not inconsistent (in a comment on #2569), and you and I have already posted our disagreement on this point there. At this point I'm sorry I even brought it up again. |
Even without the brackets and semicolon, we can still parse attributes
|
@liigo Until #11886 lands, one needs a terminator to tell whether an attribute is (The above note is just about parser-ambiguities; a separate topic from the question of user-experience, which I am also concerned about, but is more subjective and/or requires user testing for which we do not have resources currently.) (Also, for outer attributes, the item itself acts as a the terminator, which I believe is why the previous bracket-less suggestion terminated by semi-colons would have "worked." But at this point I have said I am fine with the approach outlined on this ticket.) |
@thehydroimpulse I've told you wrong on the attr-shebang test. What we're trying to test for is that rust doesn't interpret an inner attribute on the first line as a shebang (Rust ignores shebangs), but the test case I gave you uses an outer attr instead of inner. Something like this might be more appropriate:
The code for parsing shebangs is here. From reading it, it will interpret the the first two bytes of a file being '#!' as a shebang. I think the rule should be more like: if the first two characters are '#!' and the first three characters not counting whitespace are not '#![', then discard the first line as a shebang. Note that unfortunately there's a second shebang parser here that is just used for pretty printing. That also needs to be changed to follow the same rule. |
self.fatal("an inner attribute was not permitted in this context."); | ||
} | ||
} else { | ||
warned = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think warned
is necessary. The message here is different from the warn below. Although the refer to the same new syntax, they are warning about different things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@flaper87 There was two warning calls for using the old syntax. The second warn is just about the extra semicolon though, so I see your point. But, any old syntax will now print one warning instead of two.
@thehydroimpulse, it looks like @brson's comment about shebangs still needs to get addressed. If you're running low on time, though, I can take over if you want! |
Yup. I just need to push my changes which I'll do that today.
|
Signed-off-by: Daniel Fagnan <dnfagnan@gmail.com>
Signed-off-by: Daniel Fagnan <dnfagnan@gmail.com>
Signed-off-by: Daniel Fagnan <dnfagnan@gmail.com>
@alexcrichton I've been getting the same error from Travis locally, too. Not sure what's going on. Rebase, re-configuring, and cleaning doesn't fix it.
|
|
||
// EFFECT: Peek 'n' characters ahead. | ||
pub fn peek(rdr: &StringReader, n: uint) -> Option<char> { | ||
let offset = byte_offset(rdr, rdr.pos.get()).to_uint() + (n - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a dubious method, because this isn't looking n
characters ahead, but rather n
bytes ahead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, makes sense. I basically followed what nextch
had, but also having the ability to specify more than one to be peeked. This was the simpler option to forget/rollback.
That test failure looks like the attributes aren't getting parsed correctly. Looking at the code, I'm not entirely sure why, but I would recommend dumping the AST of some small programs to take a look at what's happening with the attributes. |
|
||
let style = if permit_inner { | ||
|
||
if self.eat(&token::SEMI) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Judging by the previous if
statement, it looks like this should be structured as if permit_inner && self.eat(&token::SEMI)
rather than permit_inner
always parsing an inner attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic should also change, the semicolon no longer dictates whether it's an inner attribute, something will need to get done when the !
is parsed.
@thehydroimpulse it'd be awesome to get this in for the 0.10 release (coming up soon-ish), would you like me to rebase and take over? |
Yeah, I botched my setup on this branch and can't seem to rebuild it. So
|
Ok, thanks for your work! |
This implements the currently leading (inner) attribute syntax (#2569) while keeping backwards compatibility. Everything compiles and passes (including two new tests).
New Syntax:
inner:
#![foo(bar)]
(without a semicolon)outer: stays the same.
The new syntax also supports semicolons for backward compability.